﻿using Abp.Authorization;
using Abp.Linq.Expressions;
using Abp.UI;
using Basefr.App;
using Basefr.App.Helper;
using Basefr.Consts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using MySql.Data.MySqlClient;
using Paas.App.Interface.Meta;
using Paas.App.Interface.Meta.Dtos;
using Paas.App.Interface.Meta.Messages;
using Paas.Core;
using Paas.Core.Const.Enums;
using Paas.Core.Meta.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Paas.App.Meta
{
    [Route("meta-metaObject")]

    [AbpAuthorize()]
    public class MetaObjectAppService: AppService, IMetaObjectAppService
    {
        /// <summary>
        /// 租户数据数据库连接字符串
        /// </summary>
        private readonly string customerConStr;
        private readonly IMainRepository<MetaObject,Guid> _metaObjectRepo;
        private readonly IMainRepository<MetaField, Guid> _metaFieldRepo;
        private readonly IMainRepository<Application> _applicationRepo;


        public MetaObjectAppService(IConfiguration configuration, IMainRepository<MetaObject,Guid> metaObjectRepo, IMainRepository<MetaField, Guid> metaFieldRepo, IMainRepository<Application> applicationRepo)
        {
            customerConStr=configuration[ConnectionStringNames.Customer];
            _metaObjectRepo = metaObjectRepo;
            _metaFieldRepo = metaFieldRepo;
            _applicationRepo = applicationRepo;
        }

        #region 增改
        [HttpPost(nameof(SaveMetaObject))]
        public async Task<SaveMetaObjectOutput> SaveMetaObject(SaveMetaObjectInput input)
        {
            if (input == null) throw new UserFriendlyException("保存元对象信息失败：input为空！");
            var entity = ObjectMapper.Map<MetaObject>(input.Item);
            if (input.Item?.Id != null && input.Item?.Id != Guid.Empty)
            {
                //var uData = await _MetaObjectRepo.GetAsync(input.Item.Id);
                //if (uData == null) throw new UserFriendlyException("未找到需要更新的对象！");
                //uData.Description = input.Item.Description;
                await _metaObjectRepo.UpdateAsync(entity); ;
                return new SaveMetaObjectOutput();
            }

            //设置一些默认的值
            entity.MetaDataType = MetaDataType.Custom;
            entity.MetaObjectGroup = "default";
            entity.CurrentStatus ??= MetaStatus.New;
            entity.IsPublic = true;

            var id=await _metaObjectRepo.InsertAndGetIdAsync(entity);

            return new SaveMetaObjectOutput();
        }

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        [HttpPost(nameof(PublicMetaObject))]
        public async Task PublicMetaObject(PublicMetaObjectInput input)
        {
            if (input!=null&&input?.Ids.Count>0)
            {
                foreach (var item in input.Ids)
                {
                    var uData = await _metaObjectRepo.FirstOrDefaultAsync(item);
                    if (uData == null) throw new UserFriendlyException("未找到需要更新的对象！");
                    //首次发布时:创建Table,增加对象默认字段并在App数据库中创建
                    if (uData.CurrentStatus==MetaStatus.New)
                    {
                        // 获取应用名即是数据库名称
                        if(uData.ApplicationId==null) throw new UserFriendlyException($"{uData.Label}对象应用字段为Null！无法发布！");
                        var dataBaseName = _applicationRepo.FirstOrDefault((int)uData.ApplicationId)?.Name;
                        if (dataBaseName==null) throw new UserFriendlyException($"{uData.Label}对象未找到对应的应用！无法发布！");

                        //新建对象增加默认字段
                        var fieldEntity = new MetaField()
                        {
                            MetaDataType = MetaDataType.Standard,
                            CurrentStatus = MetaStatus.Released,
                            DataType = DataType.Text,
                            //DefaultValue = Guid.NewGuid().ToString(),
                            Description = "主键",
                            IsRequired = true,
                            Label = "ID",
                            MetaFieldGroup = "Init",
                            Name = "Id",
                            ObjectId = uData.Id.ToString(),
                            ApplicationId=uData.ApplicationId
                        };
                        //var fieldEntity = new MetaField()
                        //{
                        //    MetaDataType = MetaDataType.Standard,
                        //    CurrentStatus = MetaStatus.Released,
                        //    DataType = DataType.Boolean,
                        //    DefaultValue = false,
                        //    Description = "软删除时使用：删除=true，未删除=false",
                        //    IsRequired = true,
                        //    Label = "是否删除",
                        //    MetaFieldGroup = "Init",
                        //    Name = "IsDeleted",
                        //    ObjectId = uData.Id.ToString(),
                        //    ApplicationId=uData.ApplicationId
                        //};
                        await _metaFieldRepo.InsertAsync(fieldEntity);

                        // 数据库创建Table
                        var conn = customerConStr+$"Initial Catalog={dataBaseName};";
                        var _sqlHelper = new SqlHelper(conn);
                        _sqlHelper.CreateTable(uData.Name);

                        uData.CurrentStatus = MetaStatus.Released;
                        await _metaObjectRepo.UpdateAsync(uData);
                    }
                }
            }
        }

        #endregion

        #region 查
        [HttpPost(nameof(SearchMetaObject))]
        public async Task<SearchMetaObjectOutput> SearchMetaObject(SearchMetaObjectInput input)
        {
            Expression<Func<MetaObject, bool>> predicate = p => true;
            if (!string.IsNullOrWhiteSpace(input.Name))
            {
                predicate = predicate.And(p => p.Name.Contains(input.Name.Trim()));
            }
            if (!string.IsNullOrWhiteSpace(input.Label))
            {
                predicate = predicate.And(p => p.Label.Contains(input.Label.Trim()));
            }
            if (input.ApplicationId != null && input.ApplicationId != 0)
            {
                predicate = predicate.And(p => p.ApplicationId == input.ApplicationId);
            }

            var result = await _metaObjectRepo.GetAllListAsync(predicate);
            var res = result.OrderByDescending(p => p.SortNum).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();
            var totalCount = result.Count();
            var resultItems = ObjectMapper.Map<List<MetaObjectDto>>(res);
            return new SearchMetaObjectOutput { Items = resultItems, TotalCount = totalCount };
        }
        #endregion

        #region 删
        [HttpPost(nameof(DeleteMetaObject))]
        public async Task<DeleteMetaObjectOutput> DeleteMetaObject(DeleteMetaObjectInput input)
        {
            //await _metaObjectRepo.
            await _metaObjectRepo.DeleteAsync(input.Id);
            return new DeleteMetaObjectOutput();
        }
        #endregion
    }
}
